//TIPS: 实现导出修改的平滑过渡
import { $getPublishedApplicationId } from "@/utils/common";
export * from './is';
import dayjs from 'dayjs';
import { isEqual as isEqualRow, merge as lodashMerge, get as getRaw } from 'lodash-es';
import { isSetObject, isObject, isNullOrEmpty, isArray, isEmptyObject, isEmptyArr, isFunction } from '@/utils/is'

export const isEqual = isEqualRow;
export const merge = lodashMerge;
export const get = getRaw;

export function cloneDeep(obj: any) {
  // 如果当前数据不是对象类型，则不需要深拷贝，直接返回即可
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }

  return JSON.parse(JSON.stringify(obj));
}

/**
 * 获取应用ID
 */
export function getApplicationId() {
  return import.meta.env.VITE_BASE_APP_ID || $getPublishedApplicationId()
}

/**
 * 空对象判断
 */
export function $isEmptyObject(obj) {
  for (const _name in obj) {
    return false;
  }
  return true;
}

// 给数字添加千分位分隔符
export function addThousandsSeparatorToNumber(number) {
  const formatNumber = Number(number);

  // 如果当前值不能转成数字，则返回原值；否则对其添加千分位分隔符
  if (isNaN(formatNumber)) {
    return number;
  } else {
    return formatNumber.toLocaleString();
  }
}

/**
 * 获取持久化信息
 * @param key 存储的key
 */
export function localGet(key: string) {
  try {
    const result = JSON.parse(uni.getStorageSync(key) || '{}');
    if (result.hasOwnProperty('value')) {
      return result.value;
    } else {
      return result;
    }
  } catch (error) {
    return;
  }
}

interface BlockReference<T> {
  node: T | null;
}
interface HandleNode<T> {
  (node: T): T | null;
}
interface HandleLeafNode<T> {
  (node: T, reference: BlockReference<T>): void;
}
// 通过handleNode递归逐个处理树形节点、handleLeafNode对叶子节点进行处理。data为需要递归的树结构
export function traversalTreeStructure<T extends { children?: T[]; [key: string]: any }>(
  data: Array<T>,
  handleNode: HandleNode<T> = node => ({ ...node, children: [] }),
  handleLeafNode?: HandleLeafNode<T>,
  childrenKey = 'children'
): Array<T> {
  if (!isArray(data)) {
    return [];
  }
  const filterData: T[] = [];
  for (let index = 0; index < data.length; index++) {
    // 创建引用对象，用于过滤叶子节点的实现
    const reference: BlockReference<T> = { node: null };
    reference.node = handleNode(data[index]);
    if (isArray<T>(data[index][childrenKey])) {
      // 如果有children继续递归
      const result = traversalTreeStructure(data[index][childrenKey], handleNode, handleLeafNode, childrenKey);
      if (result.length && reference.node) {
        reference.node.children = result;
      }
    } else {
      handleLeafNode && handleLeafNode(data[index], reference);
    }
    reference.node && filterData.push(reference.node);
  }
  return filterData;
}

// 处理 path， path有三种形式：'a[0].b.c'、'a.0.b.c' 和 ['a','0','b','c']，需要统一处理成数组，便于后续使用
function _basePath(path: any) {
  // 若是数组，则直接返回
  if (Array.isArray(path)) return path;
  // 若有 '[',']'，则替换成将 '[' 替换成 '.',去掉 ']'
  return path.replace(/\[/g, '.').replace(/\]/g, '').split('.');
}
export function set(object: any, path: any, value: any) {
  if (typeof object !== 'object') return object;
  _basePath(path).reduce((o, k, i, _) => {
    if (i === _.length - 1) {
      // 若遍历结束直接赋值
      o[k] = value;
      return null;
    } else if (k in o) {
      // 若存在对应路径，则返回找到的对象，进行下一次遍历
      return o[k];
    } else {
      // 若不存在对应路径，则创建对应对象，若下一路径是数字，新对象赋值为空数组，否则赋值为空对象
      o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {};
      return o[k];
    }
  }, object);
  // 返回object
  return object;
}

/**
 *  条件类型枚举
 *string
 * @export
 * @enum {string}
 */
export enum ConditionType {
  // 空
  IS_NULL = 'IS_NULL',
  // 非空
  IS_NOT_NULL = 'IS_NOT_NULL',
  // 属于
  BELONG = 'BELONG',
  // 不属于
  NOT_BELONG = 'NOT_BELONG',
  // 包含
  CONTAIN = 'CONTAIN',
  // 不包含
  NOT_CONTAIN = 'NOT_CONTAIN',
  // 开头是
  PRE_IS = 'PRE_IS',
  // 开头不是
  PRE_NOT_IS = 'PRE_NOT_IS',
  // 结尾是
  END_IS = 'END_IS',
  // 结尾不是
  END_NOT_IS ='END_NOT_IS',
  // 介于
  BETWEEN = 'BETWEEN',
  // 不介于
  NOT_BETWEEN =  'NOT_BETWEEN',
  // 等于
  EQUALS = 'EQUALS',
  // 不等于
  NOT_EQUALS = 'NOT_EQUALS',
  // 某个日期之前
  DATE_LT = 'DATE_LT',
  // 某个日期之后
  DATE_GT = 'DATE_GT',
  // 全等
  EQ = 'EQ',
  // 不全等
  NE = 'NE',
  // 大于
  GT = 'GT',
  // 小于
  LT = 'LT',
  // 大于等于
  GE = 'GE',
  // 小于等于
  LE = 'LE',
  // 空数组
  IS_NULL_ARRAY = 'IS_NULL_ARRAY',
  // 非空数组
  IS_NOT_NULL_ARRAY = 'IS_NOT_NULL_ARRAY',
};
/**
 * 左值为null/undefined时，可以使用的条件类型
 */
const leftValueCanBeNull = [
  ConditionType.IS_NULL,
  ConditionType.IS_NOT_NULL,
  ConditionType.IS_NOT_NULL_ARRAY,
  ConditionType.IS_NULL_ARRAY,
  ConditionType.EQUALS,
  ConditionType.NOT_EQUALS,
  ConditionType.EQ,
  ConditionType.NE,
];

/**
 * 检查条件是否成立
 * @param leftValue
 * @param conditionType
 * @param rightValue
 * @returns
 */
export const checkCaseCondition = (leftValue: any, conditionType: ConditionType, rightValue: any) => {
  if (!conditionType) {
    return false;
  }
  // 如果当前值值不存在，且左值不能为null/undefined时 则不满足条件
  if (leftValue === undefined || leftValue === null) {
    if (!leftValueCanBeNull.includes(conditionType)) {
      return false;
    }
  }

  switch (conditionType) {
    case ConditionType.CONTAIN: // 包含
      return leftValue.indexOf(rightValue) > -1;
    case ConditionType.NOT_CONTAIN: // 不包含
      return leftValue.indexOf(rightValue) === -1;
    case ConditionType.IS_NULL: // 为空
      return !leftValue;
    case ConditionType.IS_NOT_NULL: // 非空
      return !!leftValue;
    case ConditionType.PRE_IS: // 开头是
      return leftValue.startsWith(rightValue);
    case ConditionType.PRE_NOT_IS: // 开头不是
      return !leftValue.startsWith(rightValue);
    case ConditionType.END_IS: // 结尾是
      return leftValue.endsWith(rightValue);
    case ConditionType.END_NOT_IS: // 结尾不是
      return !leftValue.endsWith(rightValue);
    case ConditionType.EQUALS: // 等于
      return leftValue == rightValue;
    case ConditionType.NOT_EQUALS: // 不等于
      return leftValue != rightValue;
    case ConditionType.GT: // 大于
      return leftValue > rightValue;
    case ConditionType.LT: // 小于
      return leftValue < rightValue;
    case ConditionType.EQ: // 全等
      return leftValue === rightValue;
    case ConditionType.NE: // 不全等
      return leftValue !== rightValue;
    case ConditionType.GE: // 大于等于
      return leftValue >= rightValue;
    case ConditionType.LE: // 小于等于
      return leftValue <= rightValue;
    case ConditionType.IS_NULL_ARRAY: //空数组
      return !leftValue.length;
    case ConditionType.IS_NOT_NULL_ARRAY: // 非空数组
      return !!leftValue.length;
    default:
      return false;
  }
};
/**
 * 在模板中渲染字符串的通用处理函数
 *
 * @param val 待渲染的值
 * @param connector 如果为数组时的连接符
 * @returns
 */
export const renderStringInTemplate = (val: any, connector = '-'): any => {
  if (isArray(val)) {
    return val.map((item: any) => renderStringInTemplate(item, connector)).join(connector);
  }
  // 只支持三种基本数据类型
  if (typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean') {
    return val;
  }
  return '';
};

// 防抖
export function debounce(fn, wait) {
  let timer = null;
  return function () {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      timer = null;
      fn.apply(this, arguments);
    }, wait);
  };
}

// 节流
export function throttle(fn, delay) {
  let lastTime = 0;
  return function () {
    let nowDate = Date.now();
    if (nowDate - lastTime > delay) {
      // 如果当前触发时间减去最后一次触发时间大于需要延迟的事件，就执行事件
      lastTime = nowDate;
      fn && fn.apply(this, arguments);
    }
  };
}

// export function merge(source, other) {
//   if (!isObject(source) || !isObject(other)) {
//     return other === undefined ? source : other;
//   }
//   // 合并两个对象的 key，另外要区分数组的初始值为 []
//   return Object.keys({
//     ...source,
//     ...other,
//   }).reduce(
//     (acc, key) => {
//       // 递归合并 value
//       source[key] = merge(source[key], other[key]);
//       acc[key] = source[key];
//       return acc;
//     },
//     Array.isArray(source) ? [] : {},
//   );
// }

/**
 * 获取两个简单数组的差集
 * @param {Array} arr1
 * @param {Array} arr2
 */
export function getDifferenceArray(arr1, arr2) {
  if (isArray(arr1) && isArray(arr2)) {
    const set1 = new Set(arr1)
    const set2 = new Set(arr2)
    return Array.from(new Set([...set1].filter(x => !set2.has(x))))
  }
  return []
}

// 根据数组[1, 1, '星期一', 2, '星期二'，使用switch case语法，数组第一个为条件，如果条件等于1，则返回星期一，如果条件等于2，则返回星期二
export function switchCase(params: any[]) {
  const [condition, ...rest] = params
  const conditionIndex = rest.indexOf(condition)
  if (conditionIndex === -1) {
    return null
  }
  return rest[conditionIndex + 1]
}

export function deepCopy(obj){
  return JSON.parse(JSON.stringify(obj));
}

/**
 * 数组/对象遍历
 * @param object 要遍历的对象
 * @param formatCallback 要执行的方法
 */
export function $each(
  object,
  formatCallback,
) {
  let index = 0;
  if (isArray(object)) {
    // Object 没有length, 只有 Array 有
    const { length } = object;
    for (; index < length; index++) {
      formatCallback(object[index], index);
    }
  } else if (isSetObject(object)) {
    for (index of object) {
      formatCallback(index);
    }
  } else if (isObject(object)) {
    for (index in object) {
      formatCallback(object[index], index);
    }
  }
}

/**
 * 收集被联动的组件信息
 * @param {*} relationSetMap 当前组件关联的联动组件信息
 * @return
 * {
 *  联动组件ID： [
 *    联动的维度A,
 *    联动的维度B
 *  ]
 * }
 */
export const collectComponentLinkage = (relationSetMap, dimensionMap = {}, reset, externalData) => {
  const componentRelationSet = {};
  $each(relationSetMap, (componentRelationList, relationKey) => {
    $each(componentRelationList, (componentRelation) => {
      // 联动关联的维度 及 组件ID
      const { relationFieldList, id } = componentRelation;

      // 遍历联动的所有维度
      relationFieldList.forEach((field) => {
        if (dimensionMap[relationKey]) {
          // active 值主要针对表格，因为表格如果设置两个联动的话，需要点击哪个联动哪一个
          const { value, dateFormat, active } = dimensionMap[relationKey];
          // 如果存在externalData，说明接的是外部数据，需要直接赋值
          if (externalData && Object.keys(externalData).length) {
            field.filterValue = externalData[Object.keys(externalData)[0]];
          } else {
            // 给字段赋值需要过滤的值
            field.filterValue = value;
          }
          // 日期类型的需要记录转换的格式
          field.filterDateFormat = dateFormat;
          // 点击的是否是需要联动的
          field.isLinkageActive = active;
        }
        // 如果点击的维度不存在，则直接return
        if (!reset && isEmptyObject(dimensionMap[relationKey])) {
          return {};
        }
        if (field.isLinkageActive) {
          // 判断是否已经存在组件id
          if (componentRelationSet[id]) {
            componentRelationSet[id].push(JSON.parse(JSON.stringify(field)));
          } else {
            componentRelationSet[id] = [JSON.parse(JSON.stringify(field))];
          }
        }
      });
    });
  });

  return componentRelationSet;
};

// 根据交互事件中选择的位置信息获取x,y值
export function getPosition(position, width, height) {
  const positionInfo = {}
  // 获取屏幕缩放
  const getElement = document.getElementById('visualizationPageRoot');
  let scale = 1;
  if (getElement.style.transform) {
    scale = getElement.style.transform.split('(')[1].split(')')[0]
  }
  // 获取可视屏幕的高度和宽度
  const clientHeight = (document.documentElement.clientHeight == 0) ? getElement.clientHeight : document.documentElement.clientHeight;
  const clientWidth = (document.documentElement.clientWidth == 0) ? getElement.clientWidth : document.documentElement.clientWidth;
  const topCenter = (clientWidth/2 - width * scale/2) / scale
  const bottomCenter = (clientHeight - height * scale ) / scale;
  const leftCenter = (clientHeight/2 - height * scale/2) / scale;
  const rightCenter = (clientWidth - width * scale) / scale;
  switch (position) {
    case 'top-center':
      positionInfo.x = topCenter;
      positionInfo.y = 0;
      break;
    case 'bottom-center':
      positionInfo.x = topCenter;
      positionInfo.y = bottomCenter;
      break;
    case 'center-center':
      positionInfo.x = topCenter;
      positionInfo.y = leftCenter;
      break;
    case 'left-center':
      positionInfo.x = 0;
      positionInfo.y = leftCenter;
      break;
    case 'right-center':
      positionInfo.x = rightCenter;
      positionInfo.y = leftCenter;
      break;
    default:
      break;
  }
  return positionInfo;
}
/**
 * 收集被跳转的组件信息
 * @param {*} relationSetMap 当前组件关联的联动组件信息
 * @return
 * [
 *  { url: '跳转地址A', target: '_self' },
 *  { url: '跳转地址B', target: '_blank' }
 * ]
 */
export function collectComponentJump(componentJumpMap, dimensionMap = {}, pageType) {
  const urlList = [];

  // 处理内部跳转、外部跳转
  const methods = {
    'inner': handleInner,
    'outer': handleOuter
  };
  // 过滤配置的跳转信息
  $each(componentJumpMap, (jumpList, type) => {
    jumpList.forEach(config => {
      const urlItem = methods[type] && methods[type](config, dimensionMap, pageType);
      urlList.push(urlItem);
    });
  });
  return urlList;
}

// 处理内部跳转数据
function handleInner(config, dimensionMap, pageType) {
  const { dashboardId, openType, params, field } = config;

  // 表格跳转只跳转当前选择的，而echarts则全部触发，使用active进行标记点击的图表
  if (dimensionMap[field] && !dimensionMap[field].active) {
    return {};
  }

  // 跳转过滤条件
  const filter = {};
  // 跳转全局参数字符串
  let globalParameterStr = '';
  // 拼装跳转请求参数
  $each(params, item => {
    const { datasetId, source: sourceFields, target: targetFields } = item;
    const sourceField = sourceFields?.field;
    const { field: targetField, parameterType: targetParameterType }= targetFields || {};
    // 获取映射的值
    const { value, dateFormat } = dimensionMap[sourceField];
    if (targetParameterType === 'dataset') {
      // 拼装过滤参数
      const requestParam = { filterValue: encodeURIComponent(value), filterDateFormat: dateFormat };

      if (filter[datasetId]) {
        filter[datasetId][targetField] = requestParam;
      } else {
        filter[datasetId] = { [targetField]: requestParam };
      }
    }
    if(targetParameterType === 'custom') {
      globalParameterStr += `&${targetField}=${encodeURIComponent(value)}`;
    }
  });
  const parameterStr = isEmptyObject(filter) ? globalParameterStr.substr(1) : `filter=${JSON.stringify(filter)}${globalParameterStr}`;
  let url = pageType ?  `${dashboardId}?type=${pageType}&${parameterStr}` :`${dashboardId}?${parameterStr}`;
  const { origin } = window.location
  // 获取当前页面地址
  let basePath = window.location.pathname
  basePath = basePath.split("/Dashboard/").shift()
  url = origin + basePath +'/Dashboard/' + url;
  // url = origin + '/adv/' + url; // 移动端当前的形式为单页面但应用，此处先处理为跳到单页面的地址中，后续变化再行调整
  return {
    url: url,
    // 跳转方式，默认新窗口
    target: openType || '_blank'
  };
}

// 处理外部跳转数据
function handleOuter(config, dimensionMap) {
  const { url, openType, fieldMap, field } = config;

  // 表格跳转只跳转当前选择的，而echarts则全部触发，使用active进行标记点击的图表
  if (dimensionMap[field] && !dimensionMap[field].active) {
    return {};
  }

  // 获取映射的值
  const mapping = {};

  /**
   * 动态生成正则表达式，进行替换相应的值
   * resource： location.origin/[国家]/[地区]/[销售人员]
   * target  :  location.origin/中国/北京/张三
   */
  let dynamicRegex = '';
  const regexPrefix = '\\[';
  const regexSuffix = '\\]';

  // 动态生成正则
  $each(fieldMap, (fieldName, key) => {
    const { value } = dimensionMap[key];
    mapping[`[${fieldName}]`] = encodeURIComponent(value);
    dynamicRegex += `${regexPrefix}${fieldName}${regexSuffix}|`;
  });

  return {
    url: dynamicRegex ? url.replace(new RegExp(dynamicRegex.substring(0, dynamicRegex.length - 1), 'g'), replacement => mapping[replacement]) : url,
    // 跳转方式，默认新窗口
    target: openType || '_blank'
  };
}

/**
 * 列表事件循环获取向前或者向后 id 标识
 * @param {*} newValue 需要特殊处理的值
 * @param {*} blockProp 组件属性，编译阶段使用
 */
export function $getCirculationKey(newValue, blockPropPanelInfo) {
  const panelList = blockPropPanelInfo.list;
  let oldValue = blockPropPanelInfo.activeKey;
  if (isEmptyArr(panelList)) { return; }
  if (newValue !== 'back' && newValue !== 'forward') {
    return newValue;
  }
  if (isNullOrEmpty(oldValue)) {
    oldValue = panelList[0].id;
  }
  let currentIndex = 0;
  panelList.forEach((item, index) => {
    if (oldValue === item.id) {
      currentIndex = index;
    }
  });
  let resultIndex = 0;
  if (newValue === 'forward') {
    if (currentIndex >= panelList.length - 1) {
      resultIndex = 0;
    } else {
      resultIndex = currentIndex + 1;
    }
  } else if (newValue === 'back') {
    if (currentIndex <= 0) {
      resultIndex = panelList.length - 1;
    } else {
      resultIndex = currentIndex - 1;
    }
  }
  blockPropPanelInfo.activeKey = panelList[resultIndex].id;
  return panelList[resultIndex].id;
}

/**
 *  获取随机ID，组件拖到预览视图后就会被设置个ID
 */
export function $guid(prefix) {
  function s4() {
    const baseNumber = 0x10000;
    const radix = 16;
    return Math.floor((1 + Math.random()) * baseNumber)
      .toString(radix)
      .substring(1);
  }

  return `${prefix ? `${prefix}-` : ''}${s4()}${s4()}-${s4()}`;
}
/*  将数字进行千分位格式化 */
export function $formatPercentage(num) {
  //  分离整数部分及小数部分
  let [intPart, pointPart] = `${num}`.split('.');

  const reg = /\d{1,3}(?=(\d{3})+$)/g;
  intPart = intPart.replace(reg, '$&,'); // 完成整数部分千分位符号插入
  pointPart = !isNullOrEmpty(pointPart) ? `.${pointPart}` : ''; // 如果分离出的小数部分存在，则补齐小数点
  return `${intPart}${pointPart}`;
}

/**
 * 处理IOS不支持直接document.title修改标题方法
 * @param title
 */
export const setPageTitle = (title) =>{
  let _body = document.getElementsByTagName('body')[0];
  document.title = title
  let _iframe = document.createElement('iframe')
  _iframe.style.display = 'none'
  _body.appendChild(_iframe)
  setTimeout(() => {
    document.body.removeChild(_iframe)
  }, 300)
}

const cloneIs = {
  Array: Array.isArray,
  Date: (val) => val instanceof Date,
  Set: (val) => Object.prototype.toString.call(val) === '[object Set]',
  Map: (val) => Object.prototype.toString.call(val) === '[object Map]',
  Object: (val) => Object.prototype.toString.call(val) === '[object Object]',
  Symbol: (val) => Object.prototype.toString.call(val) === '[object Symbol]',
  Function: (val) => Object.prototype.toString.call(val) === '[object Function]',
}

export function deepClone(value, weakMap = new WeakMap()) {

  // 2.2 函数深拷贝
  if (cloneIs.Function(value)) {
    if (/^function/.test(value.toString()) || /^\(\)/.test(value.toString()))
      return new Function('return ' + value.toString())()

    return new Function('return function ' + value.toString())()
  }

  // 3.Date 深拷贝
  if (cloneIs.Date(value)) return new Date(value.valueOf())

  // 4.判断如果是Symbol的value, 那么创建一个新的Symbol
  if (cloneIs.Symbol(value)) return Symbol(value.description)

  // 5.判断是否是Set类型 进行深拷贝
  if (cloneIs.Set(value)) {
    // 5.1 浅拷贝 直接进行解构即可
    // return new Set([...value])

    // 5.2 深拷贝
    const newSet = new Set()
    for (const item of value) newSet.add(deepClone(item), weakMap)
    return newSet
  }

  // 6.判断是否是Map类型
  if (cloneIs.Map(value)) {
    // 6.1 浅拷贝 直接进行解构即可
    // return new Map([...value])

    // 6.2 深拷贝
    const newMap = new Map()
    for (const item of value) newMap.set(deepClone(item[0], weakMap), deepClone(item[1], weakMap))
    return newMap
  }

  // 9.判断weakMap是否有值 有值的情况下就直接将值返回就可以
  if(weakMap.has(value)) return weakMap.get(value)

  // 11.2 判断数组
  if(cloneIs.Array(value)){
    const newArr = [];
    for(const item in value) newArr[item] = deepClone(value[item], weakMap);
    return newArr
  }

  // 1.如果不是对象类型则直接将当前值返回
  if (!(cloneIs.Object(value))) return value

  // 7.判断传入的对象是数组, 还是对象
  const newObj = cloneIs.Array(value) ? [] : {}

  // 10.当weakMap没有值时，将originValue作为key, newObj作为value
  weakMap.set(value, newObj)

  for (const key in value) {
    // 11.1 判断数组
    if(cloneIs.Array(value[key])) deepClone(value[key], weakMap);

    weakMap.set(value, newObj)
    // 8 进行递归调用
    newObj[key] = deepClone(value[key], weakMap)
  }

  // 4.1 对Symbol作为key进行特殊的处理 拿到对象上面的所有Symbol key，以数组形式返回
  const symbolKeys = Object.getOwnPropertySymbols(value)
  for (const sKey of symbolKeys) {

    // 4.2 这里没有必要创建一个新的Symbol
    // const newSKey = Symbol(sKey.description)

    // 4.3 直接将原来的Symbol key 拷贝到新对象上就可以了
    newObj[sKey] = deepClone(value[sKey], weakMap)
  }

  return newObj
};
/**
 * 代码中使用动态获取静态图片地址
 * @param name: asstes/images目录下的图片名称
 */
export function getAssetsFile(name) {
  return;
}

/**
 * 日期转换
 * @param {*} serial_number
 * @param {*} format
 * @returns
 * %c 月份 1-12
 * %d 月份中的第几天 01-31
 * %e 月份中的第几天 1-31
 * %f 秒的分数6位
 * %H 小时 00-23
 * %h 小时 01-12
 * %i 分钟 00-59
 * %j 一年中的某一天 001-366
 * %k 小时 00-23
 * %l 小时 01-12
 * %m 月份 01-12
 * %S 秒 00-59
 * %s 秒 00-59
 * %T 时间 24小时制
 * %Y 年份 4位
 * %y 年份 2位
 */
export function dateParse(serial_number, format) {
  const formatParse = format.replace(/(%[c|d|e|f|H|h|i|j|k|l|m|S|s|T|Y|y])/g, match => {
    switch (match) {
      case '%c':
        return 'M'
      case '%d':
        return 'DD'
      case '%e':
        return 'D'
      case '%f':
        return 'SSS'
      case '%H':
      case '%k':
      case '%T':
        return 'HH'
      case '%h':
      case '%l':
        return 'hh'
      case '%i':
        return 'mm'
      case '%m':
        return 'MM'
      case '%S':
      case '%s':
        return 'ss'
      case '%Y':
        return 'YYYY'
      case '%y':
        return 'YY'
      default:
        return match
    }
  })
  return dayjs(serial_number, formatParse).format('YYYY-MM-DD HH:mm:ss')
}
/**
 * 用于移动端单元格合并，获取当前单元格grid占比样式
 * @param {RowData} row
 * @param {ColData} col
 * @param {number} index
 * @returns
 */
export function getGridStyle(row, col, index) {
  let end = index + 1;
  if (row.__ADDITION_ROW_INFO.rowList.includes(col.dataIndex)) {
    end = index + 1 + row.__ADDITION_ROW_INFO.rowSpan;
  }
  return index + 1 + ' / ' + end;
}
/**
 * 用于移动端单元格合并，判断是否渲染当前单元格
 * @param {RowData} row
 * @param {ColData} col
 * @returns
 */
export function getCellRenderAble(row, col) {
  if (row.__ADDITION_ROW_INFO.extra && row.__ADDITION_ROW_INFO.rowList.includes(col.dataIndex)) {
    return false;
  }
  return true;
}


const dateDif = (endTime, startTime, unit = 'd') => {
  const typeMap = {
    y: 'year',
    M: 'month',
    d: 'day',
    h: 'hour',
    m: 'minute',
    s: 'second',
  };
  return dayjs(endTime).diff(dayjs(startTime), typeMap[unit], true);
};
// 公式计算处理策略函数
export const formulaStrategy = {
  IF: (condition, first, second) => (condition ? first : second),
  DATE: (serial_number) => dayjs(serial_number).format('YYYY-MM-DD'),
  DAY: (serial_number) => dayjs(serial_number).date(),
  DAYS: (endTime, startTime) => dayjs(endTime).diff(startTime, 'day'),
  SWITCH: (...args) => switchCase([...args]),
  HOUR: (serial_number) => dayjs(serial_number).hour(),
  MINUTE: (serial_number) => dayjs(serial_number).minute(),
  MONTH: (serial_number) => dayjs(serial_number).month() + 1,
  NOW: () => dayjs().format('YYYY-MM-DD HH:mm:ss'),
  SECOND: (serial_number) => dayjs(serial_number).second(),
  DATE_PARSE: (serial_number, format = '%Y-%m-%d %T:%i:%s') => dateParse(serial_number, format),
  DATEDIF: (...args) => dateDif(...args),
  CURRENT_DATE: () => dayjs().format('YYYY-MM-DD'),
  WEEK: (serial_number) => dayjs(serial_number).week(),
  // 星期天为一周的第一天 返回0 则转为 7
  DAY_OF_WEEK: (serial_number) => dayjs(serial_number).day() || 7,
  YEAR: (serial_number) => dayjs(serial_number).year(),
  ABS: (number) => Math.abs(number),
  TRUNCATE: (number) => (number?.toString().includes('-') ? Math.ceil(number) : Math.floor(number)),
  GREATEST: (...args) => Math.max(...args),
  LEAST: (...args) => Math.min(...args),
  CONCAT: (...args) => args.join(''),
  LOWER: (text = '') => text.toLowerCase(),
  UPPER: (text = '') => text.toUpperCase(),
  LEFT: (text = '', num_chars = 1) => text.slice(0, num_chars),
  RIGHT: (text = '', num_chars = 1) => text.slice(-num_chars),
};

// 获取组件参数值
export const getComponentParamsValue = (value: any) => {
  if (isFunction(value)) {
    return value();
  }
  return value;
};
